import 'package:flutter/material.dart';
import 'package:flutterapp/common/base/base_mode.dart';
import 'package:flutterapp/common/base/base_page.dart';
import 'package:flutterapp/common/base/base_provider.dart';
import 'package:flutterapp/common/constant/api.dart';
import 'package:flutterapp/common/util/sp_utils.dart';
import 'package:flutterapp/common/util/event_bus_utils.dart';
import 'package:flutterapp/common/util/log_utils.dart';
import 'package:flutterapp/common/util/toast_utils.dart';
import 'package:flutterapp/http/http_utils.dart';
import 'package:flutterapp/me/entity/register_entity.dart';
import 'package:provider/provider.dart';

import '../entity/login_entity.dart';

/// 登录注册页面
class LoginPage extends StatelessWidget {
  const LoginPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BaseProvider<LoginModel>(
      model: LoginModel(),
      modelBuilder: (context, model) {
        return BasePage(
          appBar: AppBar(
            title: Text(model.isLoginPage ? "登录" : "注册"),
            centerTitle: true,
            actions: <Widget>[
              IconButton(
                icon: Text(model.isLoginPage ? "注册" : "登录"),
                onPressed: () {
                  FocusScope.of(context).unfocus();
                  model.switchPage();
                },
              ),
            ],
          ),
          child: SingleChildScrollView(
            child: Container(
              alignment: Alignment.center,
              padding: const EdgeInsets.all(18.0),
              child: FormBodyView(),
            ),
          ),
        );
      },
    );
  }
}

///  登录注册页面body组件
class FormBodyView extends StatefulWidget {
  const FormBodyView({Key? key}) : super(key: key);

  @override
  _FormBodyViewState createState() => _FormBodyViewState();
}

class _FormBodyViewState extends State<FormBodyView> {
  TextEditingController _unameController = TextEditingController();
  TextEditingController _pwdController = TextEditingController();
  TextEditingController _rePwdController = TextEditingController();
  GlobalKey _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    LoginModel model = Provider.of(context);
    return Form(
      key: _formKey,
      // autovalidateMode: AutovalidateMode.onUserInteraction,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          //用户名
          InputView(
            controller: _unameController..text = model.userName ?? '',
            onChanged: (newValue) => model.userName = newValue,
            validator: (value) {
              return (value?.trim().length ?? 0) > 0 ? null : '用户名不能为空';
            },
            prefixIcon: Icon(Icons.person),
            showClearButton: true,
            labelText: '用户名',
            hintText: '请输入用户名',
            helperText: '亲,请输入您的用户名!',
          ),
          //密码
          InputView(
            controller: _pwdController..text = model.password ?? '',
            onChanged: (newValue) => model.password = newValue,
            validator: (value) {
              return (value?.trim().length ?? 0) >= 6
                  ? null
                  : '密码不能为空且长度不能小于6位';
            },
            prefixIcon: Icon(Icons.vpn_key_rounded),
            showObscureButton: true,
            labelText: '密码',
            hintText: '请输入密码',
            helperText: '亲,请输入您的密码!',
            margin: EdgeInsets.only(top: 18),
          ),
          //确认密码
          InputView(
            controller: _rePwdController..text = model.repassword ?? '',
            onChanged: (newValue) => model.repassword = newValue,
            isShow: !model.isLoginPage,
            validator: (value) {
              return (value?.trim().length ?? 0) >= 6
                  ? null
                  : '密码不能为空且长度不能小于6位';
            },
            prefixIcon: Icon(Icons.vpn_key_rounded),
            showObscureButton: true,
            labelText: '确认密码',
            hintText: '请再次输入密码',
            helperText: '亲,请再次输入您的密码!',
            margin: EdgeInsets.only(top: 18),
          ),
          //记住密码
          Container(
            margin: EdgeInsets.fromLTRB(20.0, 30.0, 20.0, 0.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.end,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                Checkbox(
                  value: model.rememberPassword,
                  onChanged: (b) {
                    model.switchRememberPassword(b ?? false);
                  },
                ),
                Text(
                  "记住密码?",
                  style: TextStyle(
                    fontSize: 13.0,
                    color: Colors.grey,
                  ),
                ),
              ],
            ),
          ),

          //登录注册按钮
          Container(
            width: double.infinity,
            child: ElevatedButton(
              onPressed: () {
                FocusScope.of(context).unfocus();
                FormState formState = _formKey.currentState as FormState;
                if (formState.validate()) {
                  //校验通过
                  model.submit(context);
                }
              },
              style: ButtonStyle(
                padding: MaterialStateProperty.all(EdgeInsets.all(12)),
              ),
              child: model.isLoginPage ? Text('登录') : Text('注册'),
            ),
          ),
        ],
      ),
    );
  }
}

/// 输入组件
class InputView extends StatefulWidget {
  /// 校验方法
  final FormFieldValidator<String>? validator;

  /// 前置icon组件
  final Widget? prefixIcon;

  /// 后置icon组件,如果设置了这个,那么[showObscureButton]、[showClearButton]属性将不再生效
  final Widget? suffixIcon;

  /// 标题
  final String? labelText;

  /// 输入框内部提示文案
  final String? hintText;

  /// 底部帮助提示文案
  final String? helperText;

  /// 输入类型
  final TextInputType? keyboardType;

  /// 外边距
  final EdgeInsetsGeometry? margin;

  /// 是否显示
  final bool isShow;

  /// 初始化数据
  final String? initialValue;

  /// 保存数据
  final FormFieldSetter<String>? onSaved;

  /// 数据改变
  final ValueChanged<String>? onChanged;

  /// 控制器
  final TextEditingController? controller;

  /// 是否显示模糊按钮，可以点击来隐藏输入内容
  final bool showObscureButton;

  /// 是显示一键清除按钮
  final bool showClearButton;

  const InputView(
      {Key? key,
      this.validator,
      this.prefixIcon,
      this.suffixIcon,
      this.labelText,
      this.hintText,
      this.helperText,
      this.keyboardType,
      this.margin,
      this.isShow = true,
      this.initialValue,
      this.onSaved,
      this.onChanged,
      this.controller,
      this.showObscureButton = false,
      this.showClearButton = false})
      : super(key: key);

  @override
  _InputViewState createState() => _InputViewState();
}

class _InputViewState extends State<InputView> {
  // 是否对输入内容模糊处理
  bool obscureText = false;
  @override
  Widget build(BuildContext context) {
    return Visibility(
      visible: widget.isShow,
      child: Container(
        margin: widget.margin,
        child: TextFormField(
          controller: widget.controller,
          validator: widget.validator,
          initialValue: widget.initialValue,
          onSaved: widget.onSaved,
          decoration: InputDecoration(
            labelText: widget.labelText,
            hintText: widget.hintText,
            helperText: widget.helperText,
            contentPadding: EdgeInsets.all(10.0),
            prefixIcon: widget.prefixIcon,
            suffixIcon: widget.suffixIcon ??
                Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    //清除按钮
                    Visibility(
                      visible: widget.showClearButton,
                      child: IconButton(
                        onPressed: () {
                          setState(() {
                            widget.controller?.text = '';
                            widget.onChanged?.call('');
                          });
                        },
                        icon: Icon(Icons.close),
                      ),
                    ),
                    //隐藏按钮
                    Visibility(
                      visible: widget.showObscureButton,
                      child: IconButton(
                        onPressed: () {
                          setState(() {
                            obscureText = !obscureText;
                          });
                        },
                        icon: obscureText
                            ? Icon(Icons.lock_outline)
                            : Icon(Icons.lock_open_outlined),
                      ),
                    ),
                  ],
                ),
            border: OutlineInputBorder(
              gapPadding: 5.0,
              borderRadius: BorderRadius.circular(5),
            ),
          ),
          keyboardType: widget.keyboardType,
          obscureText: obscureText,
          onChanged: widget.onChanged,
        ),
      ),
    );
  }
}

/// 数据模型
class LoginModel extends BaseModel {
  /// 当前页面类型(登录/注册)
  bool isLoginPage = true;

  /// 是否记住密码
  bool rememberPassword = false;

  /// 用户名
  String? userName;

  /// 密码
  String? password;

  /// 确认密码
  String? repassword;

  @override
  Future<bool> init() async {
    userName = await SPUtils.getInstance().getUserName();
    password = await SPUtils.getInstance().getPassword();
    rememberPassword =
        await SPUtils.getInstance().getRememberPassword() ?? false;
    notifyListeners();

    return Future.value(true);
  }

  /// 页面登录 注册切换
  switchPage() {
    isLoginPage = !isLoginPage;
    notifyListeners();
  }

  /// 记住密码切换
  switchRememberPassword(bool value) {
    rememberPassword = value;
    //记住密码
    SPUtils.getInstance().setRememberPassword(value);
    notifyListeners();
  }

  ///点击按钮提交数据
  submit(BuildContext context) {
    //登录注册逻辑
    if (isLoginPage) {
      //走登录接口
      _login(context);
    } else {
      _register(context);
    }
  }

  /// 登录方法
  _login(BuildContext context) {
    //校验参数
    if (userName?.isEmpty ?? true) {
      shortToast("用户名不能为空");
      return;
    } else if (password?.isEmpty ?? true) {
      shortToast("密码不能为空");
      return;
    }
    //开始登录
    showLoading('登录中...');
    HttpUtils.getInstance().post<LoginEntity>(
      API.login,
      queryParameters: {
        "username": userName,
        "password": password,
      },
      onSuccess: (response) {
        if (response.errorCode == 0) {
          shortToast("登录成功");
          SPUtils.getInstance().setIsLogin(true);
          SPUtils.getInstance().setUserName(userName ?? '');
          SPUtils.getInstance().setPassword(password ?? '');

          //关闭当前页面
          if (!isDispose) Navigator.pop(context, true);

          //发出通知
          EventBusUtils.instance
              .fire(BusIEvent(busIEventID: BusIEventID.login_success));
        } else {
          shortToast(response.errorMsg ?? "登录失败");
        }
      },
      onFailure: (error, stack) {
        LogUtils.e(error, stack);
        shortToast('登录失败:${error.toString()}');
      },
    ).whenComplete(() => hideLoading());
  }

  /// 注册方法
  _register(BuildContext context) {
    //校验参数
    if (userName?.isEmpty ?? true) {
      shortToast("用户名不能为空");
      return;
    } else if (password?.isEmpty ?? true) {
      shortToast("密码不能为空");
      return;
    } else if (repassword?.isEmpty ?? true) {
      shortToast("确认密码不能为空");
      return;
    } else if (password != repassword) {
      shortToast("确认密码和密码不一致,请确保两者一致");
      return;
    }
    //开始注册
    showLoading('注册中...');
    HttpUtils.getInstance()
        .post<RegisterEntity>(API.register, queryParameters: {
      "username": userName,
      "password": password,
      "repassword": repassword,
    }, onSuccess: (response) {
      if (response.errorCode == 0) {
        shortToast("注册成功");
        SPUtils.getInstance().setIsLogin(true);
        SPUtils.getInstance().setUserName(userName ?? '');
        SPUtils.getInstance().setPassword(password ?? '');

        //切换至登录页面
        if (!isDispose) switchPage();
      } else {
        shortToast(response.errorMsg ?? "注册失败");
      }
    }, onFailure: (error, stack) {
      LogUtils.e(error, stack);
      shortToast('注册失败:${error.toString()}');
    }).whenComplete(() => hideLoading());
  }
}
